package codingDudes.utils;

/**
 * This class provides methods for mathematical tasks.
 * 
 * @author Tobias Friese
 */

public class MathUtils
{
	/**
	 * Constrains a numerical input to a defined range.
	 * 
	 * @param value numerical value to constrain
	 * @param min lower limit
	 * @param max upper limit
	 * @param round defines if result shall be rounded or not
	 * 
	 * @return constrained Number
	 */
	public static double constrain(double value, double min, double max, boolean round)
	{
		if(min < max)
		{
			if(value < min) return (round ? Math.round(min) : min);
			if(value > max) return (round ? Math.round(max) : max);
		}
		
		if(min > max)
		{
			if(value > min) return (round ? Math.round(min) : min);
			if(value < max) return (round ? Math.round(max) : max);
		}
		
		if(min == max) return min;
		
		return value;
	}
	
	/**
	 * Constrains a numerical input to a defined range.
	 * 
	 * @param value numerical value to constrain
	 * @param min lower limit
	 * @param max upper limit
	 * 
	 * @return constrained Number
	 */
	public static double constrain(double value, double min, double max)
	{
		return constrain(value, min, max, false);
	}
	
	/**
	 * Calculates the distance between two 2-dimensional points.
	 * 
	 * @param x0 x value of first point
	 * @param y0 y value of first point
	 * @param x1 x value of second point
	 * @param y1 y value of second point
	 * 
	 * @return distance
	 */
	public static double dist(double x0, double y0, double x1, double y1)
	{
		double xDiff = x1 - x0;
		double yDiff = y1 - y0;
		
		return (Math.sqrt(Math.pow(xDiff, 2) + Math.pow(yDiff, 2)));
	}
	
	/**
	 * Checks if a number is in a certain range.
	 * 
	 * @param value the number to check
	 * @param min lower limit of range
	 * @param max upper limit of range
	 * 
	 * @return true if in range, false if not
	 */
	public static boolean inRange(double value, double min, double max)
	{
		if(min < max) if((value >= min) && (value <= max)) return true;
		else if(min > max) if((value >= max) && (value <= min)) return true;
		else if(min == max) return true;
		
		return false; 
	}
	
	/**
	 * Generates a random number within a predefined range.
	 * 
	 * @param min lower limit
	 * @param max upper limit
	 * @param round specifies whether the outcome should be rounded or not
	 * 
	 * @return random number
	 */
	public static double randomRange(double min, double max, boolean round)
	{
		if(round) return Math.round((Math.random() * (max - min)) + min);
		else return (Math.random() * (max - min)) + min;
	}
	
	/**
	 * Generates a random number within a predefined range.
	 * 
	 * @param min lower limit
	 * @param max upper limit
	 * 
	 * @return random number
	 */
	public static double randomRange(double min, double max)
	{
		return randomRange(min, max, false);
	}
	
	/**
	 * Converts an angle degrees into radians.
	 * 
	 * @param angleDeg angle in degrees
	 * 
	 * @return andle in radians
	 */
	public static double deg2rad(double angleDeg)
	{
		return (angleDeg * (Math.PI / 180));
	}
	
	/**
	 * Converts an angle from radians in degrees.
	 * 
	 * @param angleRad angle in radians
	 * 
	 * @return angle in degrees
	 */
	public static double rad2deg(double angleRad)
	{
		return (angleRad * (180 / Math.PI));
	}
	
	/**
	 * Calculates a value between two other values at a specific increment.
	 * 
	 * @param value1
	 * @param value2
	 * @param amt
	 * @return
	 */
	public double lerp(double value1, double value2, double amt)
	{
		amt = constrain(amt, 0, 1);
		
		if(value1 < value2) return (((value2 - value1) * amt) + value1);
		if(value1 > value2) return (((value1 - value2) * amt) + value2);
		
		return value1;
	}
}


